﻿using System;
using System.ComponentModel;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;


namespace Basic4Net.Controls
{
	/// <summary>
	/// 功能：扩展CheckBoxList控件
	/// 修改记录：1.2007-06-22 扩展必须选择验证
	///           2.2007-07-02 修改必须选择个数MinNum和MaxNum
	/// <see cref="System.Web.UI.WebControls.CheckBoxList"/>
	/// </summary>
	[ToolboxData("<{0}:BNCheckBoxList runat=\"server\"></{0}:BNCheckBoxList>")]
	public class BNCheckBoxList : CheckBoxList
	{
		#region 验证

		/// <summary>
		/// 非空验证信息
		/// </summary>
		private static readonly string MsgEmpty = " 请选择 ";
		/// <summary>
		/// 最少选择多少个的验证信息
		/// </summary>
		private static readonly string MsgMinNum = " 最少要选择 ";
		/// <summary>
		/// 最多选择多少个的验证信息
		/// </summary>
		private static readonly string MsgMaxNum = " 最多只能选择 ";
		/// <summary>
		/// 非空验证的js脚本方法名
		/// </summary>
		private static readonly string ClientValidationFunctionName = "BNCheckBoxList_ValidatorForEmpty";

		#region --- 验证公共属性

		private string strValName = string.Empty;
		/// <summary>
		/// 验证名
		/// </summary>
		[Category("Validator"),
		Description("验证名"),
		DefaultValue("")]
		public string ValName
		{
			get
			{
				return this.strValName;
			}
			set
			{
				this.strValName = value;
			}
		}

		private ValidatorDisplay eDisplay = ValidatorDisplay.Dynamic;
		/// <summary>
		/// 验证显示格式
		/// </summary>
		[Category("Validator"),
		Description("验证显示格式"),
		DefaultValue(ValidatorDisplay.Dynamic)]
		public ValidatorDisplay Display
		{
			get
			{
				return this.eDisplay;
			}
			set
			{
				this.eDisplay = value;
			}
		}

		#endregion

		#region --- 非空验证属性

		private CustomValidator ctrValEmpty = new CustomValidator();
		//private TextBox ctrTxtEmpty = new TextBox();

		private bool blValEmpty = false;
		/// <summary>
		/// 是否非空验证
		/// </summary>
		[Category("ValidatorEmpty"),
		Description("是否非空验证"),
		DefaultValue(false)]
		public bool IsValEmpty
		{
			get
			{
				return this.blValEmpty;
			}
			set
			{
				this.blValEmpty = value;
			}
		}

		/// <summary>
		/// 自定义非空验证消息
		/// </summary>
		[Category("ValidatorEmpty"),
		Description("自定义非空验证消息"),
		DefaultValue("")]
		public string ValEmptyMsg
		{
			get
			{
				return this.ctrValEmpty.ErrorMessage == string.Empty ? BNCheckBoxList.MsgEmpty + this.strValName : this.ctrValEmpty.ErrorMessage;
			}
			set
			{
				this.ctrValEmpty.ErrorMessage = value;
			}
		}

		private int _MinNum;
		/// <summary>
		/// 必须选择的最小个数
		/// </summary>
		[Category("ValidatorEmpty"),
		Description("必须选择的最小个数"),
		DefaultValue("0")]
		public int MinNum
		{
			get { return _MinNum; }
			set { _MinNum = value; }
		}

		private int _MaxNum;
		/// <summary>
		/// 必须选择的最大个数
		/// </summary>
		[Category("ValidatorEmpty"),
		Description("必须选择的最大个数"),
		DefaultValue("0")]
		public int MaxNum
		{
			get { return _MaxNum; }
			set { _MaxNum = value; }
		}


		#endregion

		#endregion

		#region 重写基类方法

		/// <summary>
		/// 重写<see cref="System.Web.UI.WebControls.BaseDataBoundControl.OnInit"/>EnsureChildControls
		/// 调用<see cref="System.Web.UI.Control.EnsureChildControls"/>方法确保子控件被创建
		/// </summary>
		/// <param name="e"><see cref="System.EventArgs"/></param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);
			this.EnsureChildControls();
		}

		/// <summary>
		/// 重写<see cref="System.Web.UI.Control.CreateChildControls"/>
		/// 如果设置<see cref="ISS.WDC.Framework.WebControls.BNCheckBoxList.IsValEmpty"/>属性为true，则添加验证控件
		/// </summary>
		protected override void CreateChildControls()
		{
			if (!ChildControlsCreated)
			{
				string strName = this.strValName;

				#region 非空验证

				if (this.blValEmpty)
				{
					#region old
					//this.ctrTxtEmpty.ID = "Txt" + this.ID;
					//this.ctrTxtEmpty.Text = "t";
					//this.ctrTxtEmpty.EnableViewState = false;
					//this.ctrTxtEmpty.Style.Add(HtmlTextWriterStyle.Visibility, "hidden");
					//this.ctrTxtEmpty.Style.Add(HtmlTextWriterStyle.Display, "none");
					//this.Controls.Add(this.ctrTxtEmpty);
					#endregion

					this.ctrValEmpty.ID = "ValEmpty";
					this.EnableViewState = false;
					this.ctrValEmpty.ServerValidate += new ServerValidateEventHandler(ctrValEmpty_ServerValidate);
					if (this.ctrValEmpty.ErrorMessage.Equals(string.Empty))
					{
						this.ctrValEmpty.ErrorMessage = this.GetErrorMessage();
					}
					//this.ctrValEmpty.ControlToValidate = this.ctrTxtEmpty.ID;
					this.ctrValEmpty.Display = this.eDisplay;
					this.ctrValEmpty.ValidationGroup = this.ValidationGroup;
					//this.ctrValEmpty.ValidateEmptyText = true;
					this.ctrValEmpty.ClientValidationFunction = BNCheckBoxList.ClientValidationFunctionName;
					this.Controls.Add(this.ctrValEmpty);

					string strScript = this.GetValEmpScript();
					if (this.Page != null &&
						!this.Page.ClientScript.IsClientScriptBlockRegistered(typeof(BNCheckBoxList), BNCheckBoxList.ClientValidationFunctionName))
					{
						this.Page.ClientScript.RegisterClientScriptBlock(typeof(BNCheckBoxList), BNCheckBoxList.ClientValidationFunctionName, strScript, true);
					}
				}

				#endregion
			}
		}

		/// <summary>
		/// 验证控件服务器端验证逻辑
		/// </summary>
		/// <param name="source"></param>
		/// <param name="args"></param>
		private void ctrValEmpty_ServerValidate(object source, ServerValidateEventArgs args)
		{
			args.IsValid = false;
			int checkNum = 0;
			foreach (ListItem item in this.Items)
			{
				if (item.Selected)
					checkNum++;
			}
			if ((this.MaxNum > 0 && checkNum > this.MinNum && checkNum < this.MaxNum) || (checkNum > this.MinNum))
				args.IsValid = true;
		}

		/// <summary>
		/// 重写<see cref="System.Web.UI.WebControls.CheckBoxList.Render"/>
		/// 如果设置<see cref="ISS.WDC.Framework.WebControls.BNCheckBoxList.IsValEmpty"/>属性为true，则输出验证控件
		/// </summary>
		/// <param name="writer"><see cref="System.Web.UI.HtmlTextWriter"/></param>
		protected override void Render(HtmlTextWriter writer)
		{
			base.Render(writer);

			#region 非空验证
			writer.Write("<br/>");
			if (this.blValEmpty)
			{
				//this.ctrTxtEmpty.RenderControl(writer);
				this.ctrValEmpty.RenderControl(writer);
			}

			#endregion
		}

		#endregion

		#region private method

		private string GetErrorMessage()
		{
			if (this.MinNum == 0 && this.MaxNum == 0)
			{
				return BNCheckBoxList.MsgEmpty + this.ValName;
			}
			if (this.MinNum > 0 && this.MaxNum > 0)
			{
				return string.Format("{0} should choice between {1} and {2}", this.ValName, this.MinNum, this.MaxNum);
			}
			string strMsg = string.Empty;
			if (this.MinNum > 0)
			{
				strMsg += this.ValName + BNCheckBoxList.MsgMinNum + this.MinNum;
			}
			if (this.MaxNum > 0)
			{
				if (strMsg.Length > 0)
					strMsg += ";";
				strMsg += this.ValName + BNCheckBoxList.MsgMaxNum + this.MaxNum;
			}
			return strMsg;
		}

		/// <summary>
		/// 获取验证脚本
		/// </summary>
		/// <returns></returns>
		private string GetValEmpScript()
		{
			StringBuilder sbScript = new StringBuilder();
			sbScript.Append("function ")
			.Append(BNCheckBoxList.ClientValidationFunctionName)
			.Append("(obj,arg){arg.IsValid=false;")
			.Append("var checkNum=0;var minNum=")
			.Append(this.MinNum)
			.Append(";var maxNum=")
			.Append(this.MaxNum)
			.Append(";var eles=document.getElementsByTagName('")
			.Append("input")
			.Append("');var len=eles.length;")
			.Append("for(var i=0;i<len;i++){var o=eles[i];")
			.Append("if(o.id.indexOf('")
			.Append(this.ClientID)
			.Append("')>-1&&")
			.Append("o.type=='checkbox'&&o.checked){checkNum++;}}")
			.Append("if((maxNum>0&&checkNum>minNum&&checkNum<maxNum)||(checkNum>minNum))arg.IsValid=true;}");
			return sbScript.ToString();
		}

		#endregion
	}
}
